export function withOpacity(color: string, opacity: number): string {
  if (opacity < 0 || opacity > 1) {
    throw new Error('Opacity should be between 0 and 1.');
  }

  // Detect the color format and delegate to the appropriate function
  if (isNamedColor(color)) {
    return withOpacityNamedColor(color, opacity);
  } else if (color.startsWith('#')) {
    return withOpacityHex(color, opacity);
  } else if (color.startsWith('rgba')) {
    return withOpacityRgba(color, opacity);
  } else if (color.startsWith('rgb')) {
    return withOpacityRgb(color, opacity);
  } else if (color.startsWith('hsla')) {
    return withOpacityHsla(color, opacity);
  } else if (color.startsWith('hsl')) {
    return withOpacityHsl(color, opacity);
  } else {
    throw new Error('Unsupported color format');
  }
}

// Helper function for HEX colors
function withOpacityHex(hex: string, opacity: number): string {
  const hexCode = hex.replace('#', '');
  const expandedHex =
    hexCode.length === 3
      ? hexCode
        .split('')
        .map((x) => x + x)
        .join('')
      : hexCode;

  const r = parseInt(expandedHex.substr(0, 2), 16);
  const g = parseInt(expandedHex.substr(2, 2), 16);
  const b = parseInt(expandedHex.substr(4, 2), 16);

  return `rgba(${r}, ${g}, ${b}, ${opacity})`;
}

// Helper function for RGB colors
function withOpacityRgb(rgb: string, opacity: number): string {
  const match = rgb.match(/^rgb\((\d+), (\d+), (\d+)\)$/);
  if (!match) {
    throw new Error('Invalid RGB color format');
  }

  const r = parseInt(match[1], 10);
  const g = parseInt(match[2], 10);
  const b = parseInt(match[3], 10);

  return `rgba(${r}, ${g}, ${b}, ${opacity})`;
}

// Helper function for RGBA colors
function withOpacityRgba(rgba: string, opacity: number): string {
  const match = rgba.match(/^rgba\((\d+), (\d+), (\d+), ([0-1]?(?:\.\d+)?)\)$/);
  if (!match) {
    throw new Error('Invalid RGBA color format');
  }

  const r = parseInt(match[1], 10);
  const g = parseInt(match[2], 10);
  const b = parseInt(match[3], 10);

  return `rgba(${r}, ${g}, ${b}, ${opacity})`;
}

// Helper function for HSL colors with opacity
function withOpacityHsl(hsl: string, opacity: number): string {
  // Updated regex to handle space-separated HSL format with optional decimals
  const match = hsl.match(/^hsl\((\d+(\.\d+)?)(?:\s+)(\d+(\.\d+)?)%\s+(\d+(\.\d+)?)%\)$/);

  if (!match) {
    throw new Error('Invalid HSL color format');
  }

  const h = match[1]; // Hue (can be an integer or decimal)
  const s = match[3]; // Saturation (can be an integer or decimal)
  const l = match[5]; // Lightness (can be an integer or decimal)

  return `hsla(${h}, ${s}%, ${l}%, ${opacity})`;
}

// Helper function for HSLA colors
function withOpacityHsla(hsla: string, opacity: number): string {
  const match = hsla.match(/^hsla\((\d+), (\d+)%?, (\d+)%?, ([0-1]?(?:\.\d+)?)\)$/);
  if (!match) {
    throw new Error('Invalid HSLA color format');
  }

  const h = match[1];
  const s = match[2];
  const l = match[3];

  return `hsla(${h}, ${s}%, ${l}%, ${opacity})`;
}

// Helper function for named colors (basic implementation)
function isNamedColor(color: string): boolean {
  const namedColors = new Set([
    'red',
    'green',
    'blue',
    'yellow',
    'black',
    'white',
    'gray',
    'orange',
    'purple',
    'brown',
    'pink',
    'cyan',
    'magenta',
    'lime',
    'teal',
    'indigo',
    'violet',
    'gold',
    'silver',
  ]);
  return namedColors.has(color.toLowerCase());
}

// Helper function for named color opacity
function withOpacityNamedColor(color: string, opacity: number): string {
  return `rgba(${namedColorToRgb(color)}, ${opacity})`;
}

// Converts a named color to RGB (simplified, basic colors only)
function namedColorToRgb(color: string): string {
  const colors: { [key: string]: string } = {
    red: '255, 0, 0',
    green: '0, 255, 0',
    blue: '0, 0, 255',
    yellow: '255, 255, 0',
    black: '0, 0, 0',
    white: '255, 255, 255',
    gray: '128, 128, 128',
    orange: '255, 165, 0',
    purple: '128, 0, 128',
    brown: '165, 42, 42',
    pink: '255, 192, 203',
    cyan: '0, 255, 255',
    magenta: '255, 0, 255',
    lime: '0, 255, 0',
    teal: '0, 128, 128',
    indigo: '75, 0, 130',
    violet: '238, 130, 238',
    gold: '255, 215, 0',
    silver: '192, 192, 192',
  };
  return colors[color.toLowerCase()] || '0, 0, 0'; // default to black if color is unknown
}
